
package GestionTablas;

import Esquemas.Atributo;
import Esquemas.Entidad;
import Esquemas.EntidadDebil;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Clase encargada de manejar las restricciones de integridad necesarias.
 * 
 * @author Carmen M. Morillo Arias, Christian Neria Suárez, Diego Ojeda García
 * 
 */

public class Restriccion {

    /**
     * Constructor de la clase
     */
    public Restriccion() {
    }        
    
    /**
     * Método que añade la restricción de clave primaria a una entidad
     * @param entidad Entidad a la que se le añade la restricción
     */
    public void anadirRestriccionClavePrimaria(Entidad entidad){
        ArrayList<Atributo> claves = entidad.getClave();        
        
        FileWriter fichero = null; 
        try {
            fichero = new FileWriter(CreaScript.getEsquema().getNombre() + ".sql",true);           
            PrintWriter pw = new PrintWriter(fichero);            
            
            pw.append("-- Restricciones de clave primaria\n");                                               
                                                            
            String clavesScript = claves.get(0).getNombre();                       
            for(int i=1;i<claves.size();i++){                
                clavesScript = clavesScript+", "+claves.get(i).getNombre();                                                      
            }            
            pw.append("ALTER TABLE "+entidad.getNombre()+" ADD PRIMARY KEY ("+clavesScript+");\n");            

            pw.close();
        } catch (IOException ex) {
            System.err.println("Error");
        }
        finally{            
            try {
                if (fichero != null)
                    fichero.close();               
            } catch (IOException ex) {
                Logger.getLogger(Restriccion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
    }
    
    /**
     * Añade atributos a una entidad débil mediante ALTER TABLE
     * @param ef entidad fuerte
     * @param ed entidad débil
     */
    public void anadirAtributosTabla(Entidad ef, EntidadDebil ed){
        ArrayList<Atributo> claves = ef.getClave();
        
        FileWriter fichero = null; 
        try {
            fichero = new FileWriter(CreaScript.getEsquema().getNombre() + ".sql",true);           
            PrintWriter pw = new PrintWriter(fichero);            
            
            pw.append("-- Añadir atributo a entidad débil\n");                                                            
                        
            for(int i=0;i<claves.size();i++){
                pw.append("ALTER TABLE "+ed.getNombre()+" ADD ("+claves.get(i).getNombre()+" "+claves.get(i).getTipo()+");\n");
            }            
            
            pw.close();
        } catch (IOException ex) {
            System.err.println("Error");
        }
        finally{            
            try {
                if (fichero != null)
                    fichero.close();               
            } catch (IOException ex) {
                Logger.getLogger(Restriccion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }    
    }
    
    /**
     * Añade restricciones de clave foránea
     * @param ef Entidad a la que hacen referencia las claves
     * @param ed Entidad a la cual se le añaden las claves foráneas
     */
    public void anadirRestriccionesClaveForanea(Entidad ef, EntidadDebil ed){
        ArrayList<Atributo> claves = ef.getClave();
        
        FileWriter fichero = null; 
        try {
            fichero = new FileWriter(CreaScript.getEsquema().getNombre() + ".sql",true);           
            PrintWriter pw = new PrintWriter(fichero);            
            
            pw.append("-- Añadir claves foráneas a entidades débiles\n");                                    
                                    
            String clavesScript = claves.get(0).getNombre();                        
            
            for(int i=1;i<claves.size();i++){
                clavesScript = clavesScript+", "+claves.get(i).getNombre();                                        
            }            
            
            pw.append("ALTER TABLE "+ed.getNombre()+" ADD CONSTRAINT fk_"+ed.getNombre()+"_"+ef.getNombre()
                    +" FOREIGN KEY("
                    +clavesScript
                    +") REFERENCES "+ef.getNombre()+ "(" + clavesScript + ");\n");                        
            pw.close();
        } catch (IOException ex) {
            System.err.println("Error");
        }
        finally{            
            try {
                if (fichero != null)
                    fichero.close();               
            } catch (IOException ex) {
                Logger.getLogger(Restriccion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }    
    }
    
    /**
     * Crea una vista para un atributo derivado
     * @param atributo Atributo derivado del cual se crea la vista
     */
    public void crearVistaAtributoDerivado(Atributo atributo){
        FileWriter fichero = null; 
        try {
            fichero = new FileWriter(CreaScript.getEsquema().getNombre() + ".sql",true);           
            PrintWriter pw = new PrintWriter(fichero);            
            
            pw.append("-- Vista para atributo derivado\n");                                    
                                                
            pw.append("-- CREATE OR REPLACE VIEW "+atributo.getNombre()+";\n");                        
            pw.close();
        } catch (IOException ex) {
            System.err.println("Error");
        }
        finally{            
            try {
                if (fichero != null)
                    fichero.close();               
            } catch (IOException ex) {
                Logger.getLogger(Restriccion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }            
    }
    
    /**
     * Crea una tabla para un atributo multievaluado
     * @param atributo Atributo multievaluado
     * @param atributosmultievaluados distintos atributos que dependen del multievaluado
     * @param e 
     */
    public void crearTablaAtributoMultievaluado(Atributo atributo, LinkedList<Atributo> atributosmultievaluados, Entidad e){
        FileWriter fichero = null; 
        try {
            fichero = new FileWriter(CreaScript.getEsquema().getNombre() + ".sql",true);           
            PrintWriter pw = new PrintWriter(fichero);                                    
            
            if (atributosmultievaluados.size() != 0)
            {
                pw.append("-- Tabla para atributo multievaluado\n"); 
                
                pw.append("DROP TABLE tabla_"+atributo.getNombre()+" CASCADE CONSTRAINTS;\n");

                pw.append("CREATE TABLE tabla_"+atributo.getNombre()+"(\n");

                for(int i=0;i<atributosmultievaluados.size()-1;i++){
                    pw.append("   "+atributosmultievaluados.get(i).getNombre()+" "+atributosmultievaluados.get(i).getTipo()+",\n");

                }
                pw.append("   "+atributosmultievaluados.get(atributosmultievaluados.size()-1).getNombre()+" "+atributosmultievaluados.get(atributosmultievaluados.size()-1).getTipo()+"\n");
                pw.append(");\n");
                
                ArrayList<Atributo> claves = e.getClave();

                String clavesScript = claves.get(0).getNombre();   
                pw.append("ALTER TABLE tabla_"+atributo.getNombre()+" ADD ("+claves.get(0).getNombre()+" "+claves.get(0).getTipo()+");\n");

                for(int i=1;i<claves.size();i++){
                    clavesScript = clavesScript+", "+claves.get(i).getNombre();  
                    pw.append("ALTER TABLE tabla_"+atributo.getNombre()+" ADD ("+claves.get(i).getNombre()+" "+claves.get(i).getTipo()+");\n");
                }                        

                pw.append("ALTER TABLE tabla_"+atributo.getNombre()+" ADD CONSTRAINT fk_"+atributo.getNombre()+"_"+e.getNombre()
                        +" FOREIGN KEY("
                        +clavesScript
                        +") REFERENCES "+e.getNombre()+ "(" + clavesScript + ");\n");  
                pw.append("ALTER TABLE tabla_"+atributo.getNombre()+" ADD PRIMARY KEY("+clavesScript+");\n");                
            }
            else{
                ArrayList<Atributo> claves = e.getClave();
                pw.append("-- Tabla para atributo multievaluado\n");  
                
                pw.append("DROP TABLE tabla_"+atributo.getNombre()+" CASCADE CONSTRAINTS;\n");

                pw.append("CREATE TABLE tabla_"+atributo.getNombre()+"(\n");
                for(int i=0;i<claves.size()-1;i++){
                    pw.append("   "+claves.get(i).getNombre()+" "+claves.get(i).getTipo()+",\n");

                }
                pw.append("   "+claves.get(claves.size()-1).getNombre()+" "+claves.get(claves.size()-1).getTipo()+"\n");
                pw.append(");\n");
                
                String clavesScript = claves.get(0).getNombre();                   
                for(int i=1;i<claves.size();i++){
                    clavesScript = clavesScript+", "+claves.get(i).getNombre();                      
                }                        

                pw.append("ALTER TABLE tabla_"+atributo.getNombre()+" ADD CONSTRAINT fk_"+atributo.getNombre()+"_"+e.getNombre()
                        +" FOREIGN KEY("
                        +clavesScript
                        +") REFERENCES "+e.getNombre()+ "(" + clavesScript + ");\n");  
                pw.append("ALTER TABLE tabla_"+atributo.getNombre()+" ADD PRIMARY KEY("+clavesScript+");\n");                
                
            
            }
            
            pw.close();                                                
        } catch (IOException ex) {
            System.err.println("Error");
        }
        finally{            
            try {
                if (fichero != null)
                    fichero.close();               
            } catch (IOException ex) {
                Logger.getLogger(Restriccion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }         
    }
    
    /**
     * Añade un atributo a una entidad
     * @param e Entidad
     * @param a Atributo a añadir
     */
    public void anadirAtributoTabla(Entidad e, Atributo a){
        FileWriter fichero = null; 
        try {
            fichero = new FileWriter(CreaScript.getEsquema().getNombre() + ".sql",true);           
            PrintWriter pw = new PrintWriter(fichero);            
            
            pw.append("-- Añadir atributos a una entidad\n");                                    
                                                
            pw.append("ALTER TABLE "+e.getNombre()+" ADD ("+a.getNombre()+" "+a.getTipo()+");\n");                        
            pw.close();
        } catch (IOException ex) {
            System.err.println("Error");
        }
        finally{            
            try {
                if (fichero != null)
                    fichero.close();               
            } catch (IOException ex) {
                Logger.getLogger(Restriccion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }        
    }
    
}
